
/* import { ext } from '@antv/matrix-util'
const transform = ext.transform*/
/**
 * 节点事件
 * @param G6
*/

export default G6 => {
  G6.registerBehavior('drag-base-node', {
    getDefaultCfg() {
      return {
        isGragging: false,
        sourceAnchorIndex: 0,
        // 记录当前拖拽模式(拖拽目标可能是节点也可能是锚点)
        dragTarget: 'node',
        dragStartNode: {},
        distance: [], // 鼠标距离节点中心位置的距离,
        isMove: false,
        groupIdList: [],
        // 用来保存旋转时脱离旋转图片任然能移动 效果
        rotateNode: null,
        // 当前选中节点
        correntNode: null
      }
    },
    getEvents() {
      return {
        'node:mousedown': 'onMousedown',
        'node:mouseup': 'onMouseup',
        'node:dragstart': 'onDragStart',
        'node:drag': 'onDrag',
        'node:dragend': 'onDragEnd',
        'node:drop': 'onDrop',
        'node:mouseenter': 'onNodeEnter',
        'node:mousemove': 'onNodeMouseMove',
        'node:mouseleave': 'onNodeLeave',
        'node:dblclick': 'onNodeDblclick',
        'mousemove': 'onMousemove',
        'mouseup': 'onMouseupTag',
        'canvas:click': 'onCanvasClick',
        'canvas:dblclick': 'onCanvasClick',
        'node:click': 'onNodeClick'
      }
    },
    shouldBegin(e) {
      return true
    },
    // 点击画布 删除所有的旋转icon
    onCanvasClick(e) {
      if (this.correntNode) {
        const node = this.correntNode.item
        setTimeout(() => {
          node.setState('rotateShow', false) // 二值状态
        })
        this.correntNode = null
      }
    },
    // 用来监听旋转移动
    onMousemove(e) {
      // console.log(e.item)
      if (this.isMove) {
        this._moveNode(e, 'move')
      }
    },
    onMouseupTag(e) {
      // console.log('鼠标释放了================')
      // 如果是拖动
      if (this.isMove) {
        this._moveNode(e, 'stop')
      }
    },
    // 双击节点
    onNodeDblclick(e) {
      const node = e.item
      // 显示当前节点的锚点
      setTimeout(() => {
        node.setState('anchorShow', true) // 二值状态
      })
      this.graph.emit('on-node-click', e)
    },
    // 点击节点
    onNodeClick(e) {
      const node = e.item
      const _preItem = this.correntNode
      // 保存 当前选中节点
      this.correntNode = e
      // 显示当前节点的锚点
      setTimeout(() => {
        if (_preItem) { // 删除之前的旋转图标
          const _preNode = _preItem.item
          _preNode.setState('rotateShow', false) // 二值状态
        }
        node.setState('anchorShow', true) // 二值状态
        node.setState('rotateShow', true) // 二值状态
        // 设置当前节点
        // node.setState('rotateIcon', 'change') // 二值状态
      })
      /* // 移除其他节点的旋转图标
      this._removeRotateIcon(e)
      console.log('移除完成，添加数据：')
      // 添加旋转图标
      const group = node.get('group')
      group.addRotateIcon()
      console.log(group)
      // 设置旋转图标位置角度
      this._setRotateIcon(e)*/

      // this.graph.emit('on-node-click', e)
    },
    onNodeMouseMove(e) {
      this.graph.emit('on-node-mousemove', e)
    },
    /**
     *
     * @param e 当前节点对象  如果不穿
     * @private
     */
    _removeRotateIcon(e) {
      /* console.log(e)
      const group = e.target.cfg*/
      if (e) {
        /* console.log('当前有旋转图标的节点：1')
        console.log(this.correntNode)*/
        // 当前节点id
        const currId = e.item.getModel().id
        const preId = this.correntNode && this.correntNode.getModel().id ? this.correntNode.getModel().id : ''
        if (preId && currId !== preId) { // 如果存在之前的节点 并且之前节点与现在点击的节点不是同一个 删除之前的旋转图标
          // console.log('移除之前的数据：')
          const group = this.correntNode.get('group')
          group && group.removeRotateIcon()
          // e.item.refresh()
        }
      } else {
        /* console.log('当前有旋转图标的节点：2')
        console.log(this.correntNode)*/
        const group = this.correntNode && this.correntNode.get('group') ? this.correntNode.get('group') : null
        group && group.removeRotateIcon()
        // e.item.refresh()
      }

      /* const ignoreNodeId = e ? e.item.getModel().id : ''
      if (this.groupList && this.groupList.length) {
        this.groupList.forEach(item => {
          if (ignoreNodeId !== item) {
            const node = this.graph.findById(item)
            const group = node.get('group')
            group && group.removeRotateIcon()
          }
        })
      }*/
    },
    // 进入节点 显示锚点
    onNodeEnter(e) {
      const node = e.item
      // 显示当前节点的锚点
      setTimeout(() => {
        node.setState('anchorShow', true) // 二值状态
      })

      // 点击节点 显示旋转图标
      /* setTimeout(() => {
        this._removeRotateIcon(e)
        console.log("移除完成，添加数据：")
        // 添加旋转图标
        const group = node.get('group')
        group.addRotateIcon()
        // 设置旋转图标位置角度
        this._setRotateIcon(e)
      }, 100)*/
    },
    _setRotateIcon(e) {
      const group = e.item.get('group')
      const nodeRect = group.getItem('node-rect')
      const shapeControlRotate = group.getItem('shapeControlRotate')
      // shapeControlRotate.show()
      const radian = nodeRect.attrs.rotateTag
      shapeControlRotate && shapeControlRotate.resetMatrix()
      shapeControlRotate.rotate(radian)
      // console.log('旋转角度：' + radian)
      // 当前选中的节点
      this.correntNode = e.item
      /* const currId = e.item.getModel().id
      const indexTag = this.groupList && this.groupList.length ? this.groupList.indexOf(currId) : -1
      if (indexTag === -1) {
        this.groupList.push(currId)
      }*/
    },
    // 光标 离开节点 一出锚点
    onNodeLeave(e) {
      const node = e.item
      // 将锚点再次隐藏
      setTimeout(() => {
        node.setState('anchorShow', false) // 二值状态
      })
    },
    _moveNode(e, tag) {
      const item = e && e.item ? e.item : this.rotateNode
      if (!item) {
        this.isMove = false
        return
      }

      switch (tag) {
        case 'start':
          this.isMove = true
          this._rotateNode(item, e)
          break
        case 'move':
          this.isMove = true
          this._rotateNode(item, e)
          break
        case 'stop':
          this.isMove = false
          this.rotateNode = null
          break
      }
    },
    _rotateNode(item, e) {
      const model = item.get('model')
      const group = item.getContainer()
      if (!group) {
        return
      }
      const p1 = {
        x: model.x,
        y: model.y
      }
      const p2 = {
        x: e.x,
        y: e.y
      }
      const radian = Math.atan2(p2.y - p1.y, p2.x - p1.x) + Math.PI / 2
      // 角度
      const angle = radian * (180 / Math.PI)
      const nodeRect = group.getItem('node-rect')
      const nodeImg = group.getItem('node-img')
      const shapeControlRotate = group.getItem('shapeControlRotate')
      nodeRect.resetMatrix()
      nodeImg.resetMatrix()
      shapeControlRotate && shapeControlRotate.resetMatrix()

      nodeRect.attr({
        rotateTag: radian
      })

      nodeImg.rotate(radian)
      nodeRect.rotate(radian)
      shapeControlRotate && shapeControlRotate.rotate(radian)

      let ids = localStorage.getItem('ids') || '{}'
      if (ids) {
        ids = JSON.parse(ids)
        ids[model.id] = radian
        localStorage.setItem('ids', JSON.stringify(ids))
      }
    },
    // 鼠标按下显示锚点光圈
    onMousedown(e) {
      if (e.target.cfg.tag === 'shapeControlRotate') {
        // debugger
        this.isMove = true
        this.rotateNode = e.item
        this._moveNode(e, 'start')
        return
      }
      // console.log('---------onMousedown---------------')
      // if (!this.shouldBegin(e)) return
      this._clearSelected(e)
      if (e.target.cfg.isAnchor) {
        // 拖拽锚点
        this.dragTarget = 'anchor'
        this.dragStartNode = {
          ...e.item._cfg,
          anchorIndex: e.target.cfg.index
        }
        const nodes = this.graph.findAll('node', node => node)

        nodes.forEach(node => {
          node.setState('anchorActived', true)
        })
      } else {
        e.item.setState('nodeState:selected', true) // 二值状态
        // console.log("鼠标按下节点 =================")
      }
      this.graph.emit('on-node-mousedown', e)
    },
    onMouseup(e) {
      // if (!this.shouldBegin(e)) return
      if (this.dragTarget === 'anchor') {
        const nodes = this.graph.findAll('node', node => node)

        nodes.forEach(node => {
          node.clearStates('anchorActived')
        })
      }
      this.graph.emit('on-node-mouseup', e)
    },
    // 拖拽开始
    onDragStart(e) {
      // console.log('----------------------drag')
      // if (!this.shouldBegin(e)) return
      const group = e.item.getContainer()

      this.isGragging = true
      this.origin = {
        x: e.x,
        y: e.y
      }
      if (e.target.get('isAnchor')) {
        this.sourceAnchorIndex = e.target.get('index')
      } else if (group.getFirst().cfg.xShapeNode) {
        // 拖拽自定义节点
        e.item.toFront()
        this.dragTarget = 'node'
        this._nodeOnDragStart(e, group)
      }
      this.graph.emit('on-node-dragstart', e)
    },
    // 拖拽中
    onDrag(e) {
      // console.log('----------------------拖拽中')
      // if (!this.shouldBegin(e)) return
      if (this.isGragging) {
        const group = e.item.getContainer()
        if (this.dragTarget === 'node' && group.getFirst().cfg.xShapeNode) {
          this._nodeOnDrag(e, e.item.getContainer())
        }
        this.graph.emit('on-node-drag', e)
      }
    },
    // 拖拽结束
    onDragEnd(e) {
      const group = e.item.getContainer()
      this.isGragging = false
      if (this.dragTarget === 'anchor') {
        const nodes = this.graph.findAll('node', node => node)
        nodes.forEach(node => {
          node.clearStates('anchorActived')
        })
      } else if (this.dragTarget === 'node' &&
        group.getFirst().cfg.xShapeNode) {
        this._nodeOnDragEnd(e, group)
      }
      this.graph.emit('on-node-dragend', e)
    },
    delLineFun(node) {
      const group = node.group
      const removeLine = group.getItem('dashed-line')
      removeLine && removeLine.remove()
    },
    // 锚点拖拽结束添加边
    onDrop(e) {
      if (
        this.dragStartNode.id &&
        e.target.cfg.isAnchor &&
        this.dragStartNode.id !== e.target.cfg.nodeId
      ) {
        const sourceNode = this.dragStartNode.group.get('item')
        const { singleEdge } = sourceNode.getModel() // 同个source和同个target只能有1条线
        const targetAnchorIndex = e.target.get('index')
        const edges = sourceNode.getOutEdges()

        const hasLinked = edges.find(edge => {
          // sourceAnchorIndex === targetAnchorIndex, edge.source.id === source.id, edget.target.id === target.id
          if (
            (edge.get('source').get('id') === sourceNode.get('id') &&
              edge.get('target').get('id') === e.target.cfg.nodeId &&
              edge.get('sourceAnchorIndex') === this.sourceAnchorIndex &&
              edge.get('targetAnchorIndex') === targetAnchorIndex) ||
            (singleEdge &&
              edge.get('target').get('id') === e.target.cfg.nodeId)
          ) {
            return true
          }
        })

        const nodes = this.graph.findAll('node', node => node)

        nodes.forEach(node => {
          node.clearStates('anchorActived')
        })

        this.delLineFun(this.dragStartNode)
        if (!hasLinked) {
          // console.log('e.target.cfg.index==========================')
          // console.log(e.target.cfg, e)
          this.graph.emit('before-edge-add', {
            source: sourceNode,
            target: e.item.getContainer().get('item'),
            sourceAnchor: this.dragStartNode.anchorIndex,
            targetAnchor: e.target.cfg.index
          })
        }
      }
      this.graph.emit('on-node-drop', e)
    },

    /**
     * @description 判断当前画布模式是否启用了内置的 drag-node, 因为有冲突
     */
    _dragNodeModeCheck() {
      const currentMode = this.graph.get('modes')[this.graph.getCurrentMode()]

      if (currentMode.includes('drag-node')) {
        console.warn(
          'Behavior drag-shadow-node 与内置 Behavior drag-node 在行为上有冲突, 请考虑改用 setMode 来分开两种错误, 或在以上两种行为的入参 shouldBegin 方法中添加逻辑处理来避免冲突',
        )
        return true
      }
      return false
    },

    /**
     * @description 节点拖拽开始事件
     */
    _nodeOnDragStart(e, group) {
      this._dragNodeModeCheck()
      this._addShadowNode(e, group)
    },

    /**
     * @description 添加虚拟节点
     */
    _addShadowNode(e, group) {
      const item = group.get('item')
      const model = item.get('model')
      const { radius } = item.get('originStyle')
      const currentShape = item.get('currentShape')
      const { width, height, centerX, centerY } = item.getBBox()
      const shapes = item.get('shapeFactory')[currentShape]

      let { shapeType } = shapes || {}
      let attrs = {
        fillOpacity: 0.1,
        fill: '#1890FF',
        stroke: '#1890FF',
        cursor: 'move',
        lineDash: [4, 4],
        width,
        height,
        x: model.x,
        y: model.y
      }

      switch (shapeType) {
        case 'circle':
          this.distance = [e.x - centerX, e.y - centerY]
          attrs = {
            ...attrs,
            r: width / 2
          }
          break
        case 'rect':
          this.distance = [
            e.x - centerX + width / 2,
            e.y - centerY + height / 2
          ]
          attrs = {
            ...attrs,
            x: -width / 2,
            y: -height / 2,
            r: width / 2
          }
          if (radius) attrs.radius = radius
          break
        case 'ellipse':
          this.distance = [e.x - centerX, e.y - centerY]
          attrs = {
            ...attrs,
            rx: width / 2,
            ry: height / 2
          }
          break
        case 'path':
          this.distance = [e.x - centerX, e.y - centerY]
          attrs.path = item.get('keyShape').attrs.path
          attrs.size = [width, height]
          break
        case 'modelRect':
          this.distance = [
            e.x - centerX + width / 2,
            e.y - centerY + height / 2
          ]
          attrs = {
            ...attrs,
            x: -width / 2,
            y: -height / 2,
            r: width / 2
          }
          shapeType = 'rect'
          break
        default:
          shapeType = 'circle'
          break
      }

      const shadowNode = group.addShape(shapeType, {
        className: 'shadow-node',
        attrs
      })

      shadowNode.toFront()
    },

    /**
     * @description 节点拖拽事件
     */
    _nodeOnDrag(e, group) {
      // 记录鼠标拖拽时与图形中心点坐标的距离
      const item = group.get('item')
      const pathAttrs = group.getFirst()
      const { width, height, centerX, centerY } = item.getBBox()
      const shadowNode = pathAttrs.cfg.xShapeNode
        ? group.$getItem('shadow-node')
        : null
      const shapes = item.get('shapeFactory')[item.get('currentShape')]
      const { shapeType } = shapes || {}

      if (!shadowNode) {
        return console.warn('暂未支持拖拽内置节点')
      }
      if (shapeType === 'path') {
        const { type, direction } = pathAttrs.get('attrs')
        const dx = e.x - centerX - this.distance[0]
        const dy = e.y - centerY - this.distance[1]
        const path = [['Z']]

        switch (type) {
          case 'diamond-node':
            path.unshift(
              ['M', dx, dy - height / 2], // 上顶点
              ['L', dx + width / 2, dy], // 右侧顶点
              ['L', dx, dy + height / 2], // 下顶点
              ['L', dx - width / 2, dy], // 左侧顶点
            )
            break
          case 'triangle-node':
            path.unshift(
              ['L', dx + width / 2, dy], // 右侧顶点
              ['L', dx - width / 2, dy], // 左侧顶点
            )
            if (direction === 'up') {
              path.unshift(
                ['M', dx, dy - height], // 上顶点
              )
            } else {
              path.unshift(
                ['M', dx, dy + height], // 下顶点
              )
            }
            break
        }

        shadowNode.attr({
          path
        })
      } else {
        shadowNode.attr({
          x: e.x - centerX - this.distance[0],
          y: e.y - centerY - this.distance[1]
        })
      }

      shadowNode.toFront()
    },

    /**
     * @description 节点拖拽结束事件
     */
    _nodeOnDragEnd(e, group) {
      const { graph } = this
      const model = e.item.getModel()
      const shadowNode = group.getFirst().cfg.xShapeNode
        ? group.$getItem('shadow-node')
        : null

      if (shadowNode) {
        const x = e.x - this.origin.x + model.x
        const y = e.y - this.origin.y + model.y
        const pos = {
          x,
          y
        }

        shadowNode.remove()

        if (!this._dragNodeModeCheck()) {
          // 如果当前模式中没有使用内置的 drag-node 则让画布更新节点位置
          graph.updateItem(e.item, pos)
        }
      }
    },
    // 清空已选的边
    _clearSelected(e) {
      const selectedEdges = this.graph.findAllByState(
        'edge',
        'edgeState:selected',
      )
      const selectedNodes = this.graph.findAllByState('node', 'nodeState:selected')
      selectedNodes.forEach(node => {
        node.clearStates(['nodeState:selected', 'nodeState:hover'])
      })
      selectedEdges.forEach(edge => {
        edge.clearStates(['edgeState:selected', 'edgeState:hover'])
      })
      this.graph.emit('after-node-selected')
    }
  })
}
